package com.smooth.mall.service.serviceImpl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.smooth.mall.common.Constant;
import com.smooth.mall.exception.SmoothMallException;
import com.smooth.mall.exception.SmoothMallExceptionEnum;
import com.smooth.mall.filter.UserFilter;
import com.smooth.mall.model.dao.CartMapper;
import com.smooth.mall.model.dao.OrderItemMapper;
import com.smooth.mall.model.dao.OrderMapper;
import com.smooth.mall.model.dao.ProductMapper;
import com.smooth.mall.model.pojo.Order;
import com.smooth.mall.model.pojo.OrderItem;
import com.smooth.mall.model.pojo.Product;
import com.smooth.mall.model.vo.CartVO;
import com.smooth.mall.model.vo.OrderItemVO;
import com.smooth.mall.model.vo.OrderVO;
import com.smooth.mall.request.CreateOrderReq;
import com.smooth.mall.service.CartService;
import com.smooth.mall.service.OrderService;
import com.smooth.mall.utils.OrderCodeFactory;
import com.smooth.mall.utils.QRCodeGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private CartService cartService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private CartMapper cartMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Value("${file.upload.ip}")
    private String ip;

    /**
     * 创建订单
     * @param createOrderReq
     * @return
     */
    @Transactional(rollbackFor = Exception.class)//在create中遇见异常就回滚
    @Override
    public String create( CreateOrderReq createOrderReq ) {
        Integer userId = UserFilter.currentUser.getId();
        List<CartVO> cartVOList = cartService.list(userId);
        ArrayList<CartVO> cartVOArrayListTemp = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO =  cartVOList.get(i);
            if (cartVO.getSelected().equals(Constant.Cart.CHECKED)) {
                cartVOArrayListTemp.add(cartVO);
            }
        }
        cartVOList = cartVOArrayListTemp;
        if (CollectionUtils.isEmpty(cartVOList)) {
            throw new SmoothMallException(SmoothMallExceptionEnum.CART_SELECTED_EMPTY);
        }
        validSaleStatusAndStock(cartVOList);
        List<OrderItem> orderItemList = cartVOListToOrderItemList(cartVOList);
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem =  orderItemList.get(i);
            Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
            int stock = product.getStock() - orderItem.getQuantity();
            System.out.println(stock);
            if (stock < 0) {
                throw new SmoothMallException(SmoothMallExceptionEnum.NOT_ENOUGH);
            }
            product.setStock(product.getStock() - orderItem.getQuantity());
            productMapper.updateByPrimaryKeySelective(product);

        }
        cleanCart(cartVOList);
        String orderNum = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
        //创建一个订单；
        Order order = new Order();
        order.setOrderNo(orderNum);//设置订单号
        order.setUserId(userId);//设置用户id
        order.setTotalPrice(totalPrice(orderItemList));//设置订单总价
        order.setReceiverName(createOrderReq.getReceiverName());//设置收件人姓名
        order.setReceiverAddress(createOrderReq.getReceiverAddress());//设置收件人地址
        order.setReceiverMobile(createOrderReq.getReceiverMobile());//设置收件人电话
        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAY.getCode());//设置订单状态
        order.setPostage(0);//运费
        order.setPaymentType(1);
        orderMapper.insertSelective(order);
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem =  orderItemList.get(i);
            orderItem.setOrderNo(orderNum);
            orderItemMapper.insertSelective(orderItem);
        }
        return orderNum;
    }

    /**
     * 根据订单号，获取订单
     * @param orderNo
     * @return
     */
    @Override
    public OrderVO detail(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if(order == null){
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_ORDER);
        }
        Integer userId = UserFilter.currentUser.getId();
        if (!order.getUserId().equals(userId)){
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_YOURORDER);
        }
        OrderVO orderVO = getOrderVO(order);
        return orderVO;
    }

    /**
     * 前端 获取用户订单列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo listForCustomer(Integer pageNum, Integer pageSize) {
        Integer userId = UserFilter.currentUser.getId();
        List<Order> orderList = orderMapper.selectOrderForCustomer(userId);
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        PageHelper.startPage(pageNum, pageSize);
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

    /**
     *  根据订单id 取消订单
     * @param orderNo
     */
    @Override
    public void cancel(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAY.getCode())) {
            order.setOrderStatus(Constant.OrderStatusEnum.USER_CANCELED.getCode());
            order.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new SmoothMallException(SmoothMallExceptionEnum.EXCEPTION_ORDER);
        }
    }

    /**
     * 根据订单号 生成二维码支付
     * @param orderNo
     * @return
     */
    @Override
    public String qrcode(String orderNo) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String address = ip + ":" + request.getLocalPort();
        String payUrl = "http://" + address + "/pay?orderNo=" + orderNo;
        try {
            QRCodeGenerator.generateQRCodeImage(payUrl, 350, 350, Constant.FILE_UPLOAD_DIR + "QRCode/" + orderNo + ".png");
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String pngAddress = "http://" + address + "/images/" + orderNo + ".png";
        return pngAddress;
    }

    /**
     * 订单支付
     * @param orderNo
     */
    @Override
    public void pay(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus() == Constant.OrderStatusEnum.NOT_PAY.getCode()) {
            order.setOrderStatus(Constant.OrderStatusEnum.GOODS_PAID.getCode());//更改订单状态为已支付；
            order.setPayTime(new Date());//设置一下支付时间；
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new SmoothMallException(SmoothMallExceptionEnum.WRONG_ORDER);
        }
    }

    /**
     * 后端 订单分页列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo listForAdmin(Integer pageNum, Integer pageSize) {
        List<Order> orderList = orderMapper.selectOrderForAdmin();
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        PageHelper.startPage(pageNum, pageSize);
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

    /**
     * 根据订单号发货
     * @param orderNo
     */
    @Override
    public void delivered(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus() == Constant.OrderStatusEnum.GOODS_PAID.getCode()) {
            order.setOrderStatus(Constant.OrderStatusEnum.DELIVERED.getCode());//更改订单状态为已发货；
            order.setDeliveryTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new SmoothMallException(SmoothMallExceptionEnum.WRONG_ORDER);
        }
    }

    /**
     * 订单完结
     * @param orderNo
     */
    @Override
    public void finish(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new SmoothMallException(SmoothMallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus() == Constant.OrderStatusEnum.DELIVERED.getCode()) {
            order.setOrderStatus(Constant.OrderStatusEnum.DEAL_FINISHED.getCode());//更改订单状态为完结；
            order.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        } else {
            throw new SmoothMallException(SmoothMallExceptionEnum.WRONG_ORDER);
        }
    }

    private List<OrderVO> orderListToOrderVOList(List<Order> orderList) {
        List<OrderVO> orderVOList = new ArrayList<>();
        for (int i = 0; i < orderList.size(); i++) {
            Order order =  orderList.get(i);
            OrderVO orderVO = getOrderVO(order);
            orderVOList.add(orderVO);
        }
        return orderVOList;
    }

    private OrderVO getOrderVO(Order order) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());
        List<OrderItemVO> orderItemVOList = new ArrayList<>();
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem =  orderItemList.get(i);
            OrderItemVO orderItemVO = new OrderItemVO();
            BeanUtils.copyProperties(orderItem, orderItemVO);
            orderItemVOList.add(orderItemVO);
        }
        orderVO.setOrderItemVOList(orderItemVOList);
        Integer orderStatus = order.getOrderStatus();
        String orderStatusName = Constant.OrderStatusEnum.codeOf(orderStatus).getMsg();
        orderVO.setOrderStatusName(orderStatusName);
        return orderVO;
    }

    /**
     * 工具方法：判断列表中的商品是否存在、是否是上架状态、库存是否足够；
     * @param cartVOArrayList
     */
    private void validSaleStatusAndStock(List<CartVO> cartVOArrayList) {
        for (int i = 0; i < cartVOArrayList.size(); i++) {
            CartVO cartVO =  cartVOArrayList.get(i);
            Product product = productMapper.selectByPrimaryKey(cartVO.getProductId());
            if (product == null || !product.getStatus().equals(Constant.SaleStatus.SALE)) {
                throw new SmoothMallException(SmoothMallExceptionEnum.NOT_SALE);
            }
            if (cartVO.getQuantity() > product.getStock()) {
                throw new SmoothMallException(SmoothMallExceptionEnum.NOT_ENOUGH);
            }
        }
    }


    private List<OrderItem> cartVOListToOrderItemList(List<CartVO> cartVOList) {
        List<OrderItem> orderItemList = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(cartVO.getProductId());
            orderItem.setProductName(cartVO.getProductName());//商品名称
            orderItem.setProductImg(cartVO.getProductImage());//商品图片
            orderItem.setUnitPrice(cartVO.getPrice());//商品单价

            orderItem.setQuantity(cartVO.getQuantity());//商品的购买数量
            orderItem.setTotalPrice(cartVO.getTotalPrice());//商品的总价

            orderItemList.add(orderItem);
        }
        return orderItemList;
    }


    private void cleanCart(List<CartVO> cartVOList) {
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO =  cartVOList.get(i);
            cartMapper.deleteByPrimaryKey(cartVO.getId());
        }
    }


    private Integer totalPrice(List<OrderItem> orderItemList) {
        Integer totalPrice = 0;
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem =  orderItemList.get(i);
            totalPrice += orderItem.getTotalPrice();
        }
        return totalPrice;
    }
}
